package vn.bk.hotel;

import java.util.List;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuItem;
import com.google.android.gms.common.GooglePlayServicesNotAvailableException;
import com.google.android.gms.maps.CameraUpdate;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.GoogleMap.CancelableCallback;
import com.google.android.gms.maps.GoogleMap.OnCameraChangeListener;
import com.google.android.gms.maps.GoogleMap.OnMapClickListener;
import com.google.android.gms.maps.GoogleMap.OnMarkerClickListener;
import com.google.android.gms.maps.MapsInitializer;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.CameraPosition;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.LatLngBounds;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
import com.google.android.gms.maps.model.PolylineOptions;

import vn.bk.hotel.adapter.DatabaseHotel;
import vn.bk.hotel.dialog.DialogMapView;
import vn.bk.hotel.map.JSONParser;
import vn.bk.hotel.object.HotelInfo;
import vn.bk.hotel.utils.MapUtils;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RatingBar;
import android.widget.TextView;

public class ViewMap extends BaseActivity {

    public static HotelInfo myHotel;
    private LatLng myPoint;
    private GoogleMap mMap;
    private double myLat, myLong;
    private static final int CHANGE_VIEW = Menu.FIRST;
    public static boolean isDirection = true;
    private LatLngBounds.Builder bc;
    private final String TAG = "ViewMap";
    private LinearLayout frameLayout;
    private View infoWindowView;
    private TextView name, address;
    private RatingBar ratingBar;
    private DatabaseHotel myDB;

    @Override
    protected void onCreate(Bundle savedInstanceState) {

	super.onCreate(savedInstanceState);
	setContentView(R.layout.map);
	myLat = SplashScreen.latitude;
	myLong = SplashScreen.longtitude;
	// getSupportActionBar().setHomeButtonEnabled(true);
	// getSupportActionBar().setDisplayHomeAsUpEnabled(true);
	myDB = new DatabaseHotel(getApplicationContext());
	frameLayout = (LinearLayout) findViewById(R.id.layout_overlay);
	Log.i(TAG, "start load map");
	myPoint = new LatLng(myHotel.getLatitude(), myHotel.getLongitude());
	Log.i(TAG, "start initialize");
	try {
	    MapsInitializer.initialize(this);
	} catch (GooglePlayServicesNotAvailableException e) {
	    // TODO Auto-generated catch block
	    e.printStackTrace();
	}

	mMap = ((SupportMapFragment) getSupportFragmentManager()
		.findFragmentById(R.id.map)).getMap();

	// TileOverlayOptions lay = new TileOverlayOptions();

	bc = new LatLngBounds.Builder();
	if (isDirection) {
	    bc.include(new LatLng(SplashScreen.latitude,
		    SplashScreen.longtitude));
	}
	bc.include(myPoint);
	Log.i(TAG, "Camera update");
	final CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngBounds(
		bc.build(), 45);

	mMap.setOnCameraChangeListener(new OnCameraChangeListener() {

	    @Override
	    public void onCameraChange(CameraPosition arg0) {
		// TODO Auto-generated method stub
		if (isDirection) {
		    mMap.moveCamera(cameraUpdate);
		    mMap.animateCamera(cameraUpdate);
		    mMap.setOnCameraChangeListener(null);
		}
	    }
	});

	initActionMenu();
	final Marker myMarker = mMap.addMarker(new MarkerOptions().position(
		myPoint).icon(
		BitmapDescriptorFactory.fromResource(R.drawable.map_pin_normal)));
	mMap.animateCamera(CameraUpdateFactory
		.newCameraPosition(new CameraPosition(myPoint, 9, 0, 0)));
	mMap.animateCamera(CameraUpdateFactory
		.newCameraPosition(new CameraPosition(myPoint, 15, 0, 0)));

	mMap.setOnMarkerClickListener(new OnMarkerClickListener() {

	    @Override
	    public boolean onMarkerClick(Marker marker) {
		// TODO Auto-generated method stub
		if (marker.getId().equals(myMarker.getId())) {
		    addView(myHotel);
		}
		return false;
	    }
	});
	mMap.setOnMapClickListener(new OnMapClickListener() {

	    @Override
	    public void onMapClick(LatLng arg0) {
		// TODO Auto-generated method stub
		removeView();
	    }
	});
	if (isDirection) {
	    mMap.addMarker(new MarkerOptions()
		    .position(new LatLng(myLat, myLong)).title("My Location")
		    .icon(BitmapDescriptorFactory.fromResource(R.drawable.me)));
	    // ConnectAsyncTask drawMap = new ConnectAsyncTask(MapUtils.makeURL(
	    // myLat, myLong, myHotel.getLatitude(),
	    // myHotel.getLongitude()));
	    // drawMap.execute("run");
	}

    }

    private void removeView() {
	if (infoWindowView.isShown())
	    frameLayout.removeView(infoWindowView);
	Animation animation = AnimationUtils.loadAnimation(getBaseContext(),
		R.anim.transition_top_to_bottom_out);
	animation.setStartOffset(0);
	infoWindowView.startAnimation(animation);

    }

    private void addView(HotelInfo hotel) {
	if (infoWindowView == null) {
	    name.setText(hotel.getNameHotel());
	    address.setText(hotel.getAdress());
	    ratingBar.setRating(hotel.getNumRate());
	    frameLayout.addView(infoWindowView);
	    Animation animation = AnimationUtils.loadAnimation(
		    getBaseContext(), R.anim.transition_bottom_to_top);
	    animation.setStartOffset(0);
	    infoWindowView.startAnimation(animation);

	    // infoWindowView.startAnimation(animation)
	} else if (!infoWindowView.isShown()) {
	    name.setText(hotel.getNameHotel());
	    address.setText(hotel.getAdress());
	    ratingBar.setRating(hotel.getNumRate());
	    frameLayout.addView(infoWindowView);
	    Animation animation = AnimationUtils.loadAnimation(
		    getBaseContext(), R.anim.transition_bottom_to_top);
	    animation.setStartOffset(0);
	    infoWindowView.startAnimation(animation);
	}
    }

    private void initActionMenu() {
	LayoutInflater inflater = (LayoutInflater) getApplicationContext()
		.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
	infoWindowView = inflater.inflate(R.layout.overlay, null);
	name = (TextView) infoWindowView.findViewById(R.id.name_hotel_map);
	address = (TextView) infoWindowView
		.findViewById(R.id.address_hotel_map);
	ratingBar = (RatingBar) infoWindowView
		.findViewById(R.id.rating_hotel_map);
	ImageView road = (ImageView) infoWindowView
		.findViewById(R.id.img_action_road);
	ImageView call = (ImageView) infoWindowView
		.findViewById(R.id.img_action_call);
	final ImageView favorite = (ImageView) infoWindowView
		.findViewById(R.id.img_action_add_favorite);
	if (!isDirection) {
	    road.setImageResource(R.drawable.road_disable_map);
	} else {
	    road.setImageResource(R.drawable.road_map);
	}
	if (myDB.isExistInDatabase(myHotel)) {
	    favorite.setImageResource(R.drawable.favorite_map);
	} else {
	    favorite.setImageResource(R.drawable.favorite_disable_map);
	}
	road.setOnClickListener(new OnClickListener() {

	    @Override
	    public void onClick(View v) {

		if (isDirection) {
		    removeView();
		    new ConnectAsyncTask(MapUtils.makeURL(
			    SplashScreen.latitude,
			    SplashScreen.longtitude, myHotel.getLatitude(),
			    myHotel.getLongitude())).execute();
		}
	    }
	});
	call.setOnClickListener(new OnClickListener() {

	    @Override
	    public void onClick(View v) {
		removeView();
		Intent localIntent = new Intent("android.intent.action.DIAL",
			Uri.parse("tel:" + myHotel.getPhone()));
		startActivity(localIntent);
	    }
	});
	favorite.setOnClickListener(new OnClickListener() {

	    @Override
	    public void onClick(View v) {
		if (myDB.isExistInDatabase(myHotel)) {
		    favorite.setImageResource(R.drawable.favorite_disable_map);
		    myDB.deleteHotel(myHotel);
		} else {
		    favorite.setImageResource(R.drawable.favorite_map);
		    myDB.createHotel(myHotel);
		}
	    }
	});

    }

    public void animateCameraTo(final double lat, final double lng) {

	CameraPosition camPosition = mMap.getCameraPosition();
	if (!((Math.floor(camPosition.target.latitude * 100) / 100) == (Math
		.floor(lat * 100) / 100) && (Math
		.floor(camPosition.target.longitude * 100) / 100) == (Math
		.floor(lng * 100) / 100))) {
	    mMap.getUiSettings().setScrollGesturesEnabled(false);
	    mMap.animateCamera(
		    CameraUpdateFactory.newLatLng(new LatLng(lat, lng)),
		    new CancelableCallback() {

			@Override
			public void onFinish() {
			    mMap.getUiSettings().setScrollGesturesEnabled(true);

			}

			@Override
			public void onCancel() {
			    mMap.getUiSettings().setAllGesturesEnabled(true);

			}
		    });
	}

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
	// TODO Auto-generated method stub
	menu.add(0, CHANGE_VIEW, 0, "Change View").setIcon(
		R.drawable.view_change);
	return super.onCreateOptionsMenu(menu);
    }

    public void changeMapView(int type) {
	if (type == DialogMapView.NORMAL) {
	    mMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
	} else {
	    mMap.setMapType(GoogleMap.MAP_TYPE_SATELLITE);
	}
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
	// TODO Auto-generated method stub
	if (item.getItemId() == CHANGE_VIEW) {
	    DialogMapView dialog = new DialogMapView(this);
	    dialog.show();
	}
	return super.onOptionsItemSelected(item);
    }

    public void drawPath(String result) {

	try {
	    // Tranform the string into a json object
	    final JSONObject json = new JSONObject(result);
	    JSONArray routeArray = json.getJSONArray("routes");
	    JSONObject routes = routeArray.getJSONObject(0);
	    JSONObject overviewPolylines = routes
		    .getJSONObject("overview_polyline");
	    String encodedString = overviewPolylines.getString("points");
	    List<LatLng> list = MapUtils.decodePoly(encodedString);

	    for (int z = 0; z < list.size() - 1; z++) {
		LatLng src = list.get(z);
		LatLng dest = list.get(z + 1);
		mMap.addPolyline(new PolylineOptions()
			.add(new LatLng(src.latitude, src.longitude),
				new LatLng(dest.latitude, dest.longitude))
			.width(8).color(Color.RED).geodesic(true));
	    }

	} catch (JSONException e) {

	}
    }

    private class ConnectAsyncTask extends AsyncTask<String, Integer, String> {
	private ProgressDialog progressDialog;
	String url;

	ConnectAsyncTask(String urlPass) {
	    url = urlPass;
	}

	@Override
	protected void onPreExecute() {
	    // TODO Auto-generated method stub
	    super.onPreExecute();
	    progressDialog = new ProgressDialog(ViewMap.this);
	    progressDialog.setMessage(ViewMap.this
		    .getString(R.string.find_route));
	    progressDialog.setIndeterminate(true);
	    progressDialog.show();
	}

	@Override
	protected String doInBackground(String... params) {
	    JSONParser jParser = new JSONParser();
	    String json = jParser.getJSONFromUrl(url);
	    return json;
	}

	@Override
	protected void onPostExecute(String result) {
	    super.onPostExecute(result);
	    progressDialog.dismiss();
	    if (result != null) {
		drawPath(result);
	    }
	}
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
	// TODO Auto-generated method stub
	if (keyCode == KeyEvent.KEYCODE_BACK) {
	    if (infoWindowView.isShown()) {
		removeView();
	    } else {
		finish();
	    }
	}
	return false;
    }

}
